home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved.
- Distributed by Free Software Foundation, Inc.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* gdevbgi.c */
- /* Ghostscript driver for Borland Graphics Interface (BGI) */
- #include <string.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <graphics.h>
- #include "gx.h"
- #include "gxdevice.h"
-
- #ifndef BGI_LIB /* may be set in makefile */
- # define BGI_LIB ""
- #endif
-
- /*
- * BGI supports these video cards:
- * Hercules, CGA, MCGA, EGA, VGA, AT&T 400, IBM 8514, PC3270.
- * Highest resolution mode is used with all these video cards.
- * EGA and VGA display 16 colors, the rest are black-and-white only.
- * In addition, the environment variable BGIUSER may be used
- * to define a user-supplied Super VGA driver: see the use.doc file
- * for details.
- */
- #define SUPER_VGA 999 /* bogus # for user-defined driver */
-
- /* See gxdevice.h for the definitions of the procedures. */
-
- dev_proc_open_device(bgi_open);
- dev_proc_close_device(bgi_close);
- dev_proc_map_rgb_color(bgi_map_rgb_color);
- dev_proc_map_color_rgb(bgi_map_color_rgb);
- dev_proc_fill_rectangle(bgi_fill_rectangle);
- dev_proc_tile_rectangle(bgi_tile_rectangle);
- dev_proc_copy_mono(bgi_copy_mono);
- dev_proc_copy_color(bgi_copy_color);
- dev_proc_draw_line(bgi_draw_line);
-
- /* The device descriptor */
- typedef struct gx_device_bgi_s gx_device_bgi;
- struct gx_device_bgi_s {
- gx_device_common;
- int display_mode;
- struct text_info text_mode;
- };
- #define bgi_dev ((gx_device_bgi *)dev)
- static gx_device_procs bgi_procs = {
- bgi_open,
- gx_default_get_initial_matrix,
- gx_default_sync_output,
- gx_default_output_page,
- bgi_close,
- bgi_map_rgb_color,
- bgi_map_color_rgb,
- bgi_fill_rectangle,
- bgi_tile_rectangle,
- bgi_copy_mono,
- bgi_copy_color,
- bgi_draw_line,
- gx_default_get_bits,
- gx_default_get_props,
- gx_default_put_props
- };
- gx_device_bgi gs_bgi_device = {
- sizeof(gx_device_bgi),
- &bgi_procs,
- "bgi",
- 0, 0, /* width and height are set in bgi_open */
- 1, 1, /* density is set in bgi_open */
- no_margins,
- dci_black_and_white,
- 0 /* not open yet */
- };
-
- /* Detection procedure for user-defined driver. */
- private int huge
- detectVGA()
- { return gs_bgi_device.display_mode;
- }
-
- /* Open the BGI driver for graphics mode */
- int
- bgi_open(gx_device *dev)
- { int driver, mode;
- char *bgi_user = getenv("BGIUSER");
- char *bgi_path = getenv("BGIPATH");
-
- gettextinfo(&bgi_dev->text_mode);
-
- if ( bgi_path == NULL )
- bgi_path = BGI_LIB;
- if ( bgi_user != NULL )
- { /* A user-supplied driver is specified as "mode.dname", */
- /* where mode is a hex number and dname is the name */
- /* of the driver file. */
- char dname[40];
- if ( strlen(bgi_user) > sizeof(dname) ||
- sscanf(bgi_user, "%x.%s", &mode, dname) != 2
- )
- { eprintf("BGIUSER not in form nn.dname.\n");
- exit(1);
- }
- gs_bgi_device.display_mode = mode; /* sigh.... */
- installuserdriver(dname, detectVGA);
- driver = DETECT;
- initgraph(&driver, &mode, bgi_path);
- driver = SUPER_VGA;
- }
- else /* not user-defined driver */
- { /* We include the CGA and Hercules drivers */
- /* in the Ghostscript executable, so end-users don't */
- /* have to have the BGI files. */
- if ( registerbgidriver(CGA_driver) < 0 )
- { eprintf("BGI: Can't register CGA driver!\n");
- exit(1);
- }
- if ( registerbgidriver(Herc_driver) < 0 )
- { eprintf("BGI: Can't register Hercules driver!\n");
- exit(1);
- }
-
- detectgraph(&driver, &mode);
- if ( driver < 0 )
- { eprintf("BGI: No graphics hardware detected!\n");
- exit(1);
- }
-
- if ( driver == EGA64 )
- { /* Select 16 color video mode if video card is EGA with 64 Kb of memory */
- mode = EGA64LO;
- }
-
- /* Initialize graphics mode. */
-
- /* Following patch for AT&T 6300 is courtesy of */
- /* Allan Wax, Xerox Corp. */
- if ( driver == CGA )
- { /* The actual hardware might be an AT&T 6300. */
- /* Try initializing it that way. */
- int save_mode = mode;
- driver = ATT400, mode = ATT400HI;
- initgraph(&driver, &mode, bgi_path);
- if ( graphresult() != grOk )
- { /* Nope, it was a real CGA. */
- closegraph();
- driver = CGA, mode = save_mode;
- initgraph(&driver, &mode, bgi_path);
- }
- }
- else
- initgraph(&driver, &mode, bgi_path);
- }
-
- { int code = graphresult();
- if ( code != grOk )
- { eprintf1("Error initializing BGI driver: %s\n",
- grapherrormsg(code));
- exit(1);
- }
- }
-
- /* Set parameters that were unknown before opening device */
-
- /* Size and nominal density of screen. */
- /* The following algorithm maps an appropriate fraction of */
- /* the display screen to an 8.5" x 11" coordinate space. */
- /* This may or may not be what is desired! */
- if ( dev->width == 0 )
- dev->width = getmaxx() + 1;
- if ( dev->height == 0 )
- dev->height = getmaxy() + 1;
- if ( dev->y_pixels_per_inch == 1 )
- { /* Get the aspect ratio from the driver. */
- int arx, ary;
- getaspectratio(&arx, &ary);
- dev->y_pixels_per_inch = dev->height / 11.0;
- dev->x_pixels_per_inch =
- dev->y_pixels_per_inch * ((float)ary / arx);
- }
-
- /* Find out if the device supports color */
- /* (default initialization is monochrome). */
- /* We only recognize 16-color devices right now. */
- if ( getmaxcolor() > 1 )
- { static gx_device_color_info bgi_16color = dci_color(4, 2, 3);
- dev->color_info = bgi_16color;
- }
- return 0;
- }
-
- /* Close the BGI driver */
- int
- bgi_close(gx_device *dev)
- { closegraph();
- textmode(bgi_dev->text_mode.currmode);
- return 0;
- }
-
- /* Map a r-g-b color to the 16 colors available with an EGA/VGA video card. */
- gx_color_index
- bgi_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
- gx_color_value b)
- { return (gx_color_index)
- ((r > gx_max_color_value / 4 ? 4 : 0) +
- (g > gx_max_color_value / 4 ? 2 : 0) +
- (b > gx_max_color_value / 4 ? 1 : 0) +
- (r > gx_max_color_value / 4 * 3 ||
- g > gx_max_color_value / 4 * 3 ? 8 : 0));
- }
-
- /* Map a color code to r-g-b. Surprisingly enough, this is algorithmic. */
- int
- bgi_map_color_rgb(gx_device *dev, gx_color_index color,
- gx_color_value prgb[3])
- {
- #define icolor (int)color
- gx_color_value one =
- (icolor & 8 ? gx_max_color_value : gx_max_color_value / 3);
- prgb[0] = (icolor & 4 ? one : 0);
- prgb[1] = (icolor & 2 ? one : 0);
- prgb[2] = (icolor & 1 ? one : 0);
- return 0;
- #undef icolor
- }
-
- /* Copy a monochrome bitmap. The colors are given explicitly. */
- /* Color = gx_no_color_index means transparent (no effect on the image). */
- int
- bgi_copy_mono(gx_device *dev,
- const byte *base, int sourcex, int raster, gx_bitmap_id id,
- int x, int y, int w, int h,
- gx_color_index zero, gx_color_index one)
- { const byte *ptr_line = base + (sourcex >> 3);
- int left_bit = 0x80 >> (sourcex & 7);
- int dest_y = y, end_x = x + w;
- int invert = 0;
- int color;
-
- if ( zero == gx_no_color_index )
- { if ( one == gx_no_color_index ) return 0;
- color = (int)one;
- }
- else
- { if ( one == gx_no_color_index )
- { color = (int)zero;
- invert = -1;
- }
- else
- { /* Pre-clear the rectangle to zero */
- setfillstyle(SOLID_FILL, (int)zero);
- bar(x, y, x + w - 1, y + h - 1);
- color = (int)one;
- }
- }
-
- while ( h-- ) /* for each line */
- { const byte *ptr_source = ptr_line;
- register int dest_x = x;
- register int bit = left_bit;
- while ( dest_x < end_x ) /* for each bit in the line */
- { if ( (*ptr_source ^ invert) & bit )
- putpixel(dest_x, dest_y, color);
- dest_x++;
- if ( (bit >>= 1) == 0 )
- bit = 0x80, ptr_source++;
- }
- dest_y++;
- ptr_line += raster;
- }
- return 0;
- }
-
-
- /* Copy a color pixel map. This is just like a bitmap, except that */
- /* each pixel takes 4 bits instead of 1 when device driver has color. */
- int
- bgi_copy_color(gx_device *dev,
- const byte *base, int sourcex, int raster, gx_bitmap_id id,
- int x, int y, int w, int h)
- { if ( gx_device_has_color(dev) )
- { /* color device, four bits per pixel */
- const byte *line = base + (sourcex >> 1);
- int dest_y = y, end_x = x + w;
-
- if ( w <= 0 ) return 0;
- while ( h-- ) /* for each line */
- { const byte *source = line;
- register int dest_x = x;
- if ( sourcex & 1 ) /* odd nibble first */
- { int color = *source++ & 0xf;
- putpixel(dest_x, dest_y, color);
- dest_x++;
- }
- /* Now do full bytes */
- while ( dest_x < end_x )
- { int color = *source >> 4;
- putpixel(dest_x, dest_y, color);
- dest_x++;
- if ( dest_x < end_x )
- { color = *source++ & 0xf;
- putpixel(dest_x, dest_y, color);
- dest_x++;
- }
- }
- dest_y++;
- line += raster;
- }
- }
- else /* monochrome device: one bit per pixel */
- { /* bitmap is the same as bgi_copy_mono: one bit per pixel */
- bgi_copy_mono(dev, base, sourcex, raster, id, x, y, w, h,
- (gx_color_index)BLACK, (gx_color_index)WHITE);
- }
- return 0;
- }
-
-
- /* Fill a rectangle. */
- int
- bgi_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
- gx_color_index color)
- { setfillstyle(SOLID_FILL, (int)color);
- bar(x, y, x + w - 1, y + h - 1);
- return 0;
- }
-
-
- /* Tile a rectangle. If neither color is transparent, */
- /* pre-clear the rectangle to color0 and just tile with color1. */
- /* This is faster because of how bgi_copy_mono is implemented. */
- /* Note that this also does the right thing for colored tiles. */
- int
- bgi_tile_rectangle(gx_device *dev, const gx_bitmap *tile,
- int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
- int px, int py)
- { if ( czero != gx_no_color_index && cone != gx_no_color_index )
- { bgi_fill_rectangle(dev, x, y, w, h, czero);
- czero = gx_no_color_index;
- }
- return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py);
- }
-
-
- /* Draw a line */
- int
- bgi_draw_line(gx_device *dev, int x0, int y0, int x1, int y1,
- gx_color_index color)
- { setcolor((int)color);
- setlinestyle(SOLID_LINE, 0, NORM_WIDTH); /* solid, one pixel wide */
- line(x0, y0, x1, y1);
- return 0;
- }
-